<html>
    <head>
        <title>IHasExtraProperties接口</title>
    </head>
    <body>
        <script>
            //  对象扩展

                    /*
                        ABP 提供了一个 "对象扩展系统"，允许你在"不修改相关类的情况下向现有对象添加额外的属性。"

                        这允许扩展"由依赖的模块实现的功能"，尤其是当你想要扩展模块定义的"实体"和"Dto"时。

                        （你自己的对象通常不需要对象扩展系统，因为你可以轻松的将常规属性添加到你自己的类中）
                    */


                    /*
                        一、 IHasExtraProerties接口

                            这个接口，是让一个类"可以被扩展"的接口。 接口内部只是定义了一个 字典Dictionary属性：

                                ExtraPropertyDictionary ExtraProperties { get; }

                            ExtraPropertyDictionary类继承自Dictionary<string, object>类。你可以使用此字典添加或获取额外的属性。


                            1、abp中实现了IHasExtraProerties接口的基类：
                                  ①、AggregateRoot 类
                                  ②、ExtensibleEntityDto类、ExtensibleAuditedEntityDto类
                                  ③、由ExtensibleObject实现，这是一个简单的基类，可以继承任何类型的对象。

                                  因此，如果你从这些类继承，你的类也将是可扩展的。如果没有，你可以随时手动实现它。

                            2、基本扩展方法

                                   虽然你可以直接使用类的 ExtraProperties 属性，但是建议在处理额外属性时使用以下扩展方法：

                                   ①、SetProperty()方法，设置属性
                                            user.SetProperty("Title", "My Title");
                                            user.SetProperty("IsSuperUser", true);

                                        SetPprperty()方法返回当前对象，所以你可以链式调用：
                                            user.SetProperty("Title", "My Title")
                                                .SetProperty("IsSuperUser", true);

                                    ②、GetPropery()方法，用于读取额外属性的值：

                                            var title = user.GetProperty<string>("Title");

                                            if (user.GetProperty<bool>("IsSuperUser"))
                                            {
                                                //...
                                            }
                                            
                                            GetProperty是一个泛型方法，将对象类型作为泛型参数。

                                    ③、非原始类型属性
                                           如果你的属性类型不是原始数据类型(int、bool、enum、string....)，则需要使用返回object的GetProperty的非泛型版本。

                                    ④、HasProperty()方法，用于检查是否存在某个属性：

                                    ⑤、RemoveProperty()方法，用于移除某个属性：



                            3、一些最佳实践
                                    
                                    为属性名称使用魔术字符串是危险的，因为你很容易键入错误的属性名称---它不是类型安全的：

                                    相伴，你需要：
                                            ①、 为你的属性名称定义一个常量，并将其用作属性名称。

                                            ②、创建扩展方法以轻松设置你的额外属性

                                            eg:
                                                public static class IdentityUserExtensions
                                                {
                                                    private const string TitlePropertyName = "Title";

                                                    public static void SetTitle(this IdentityUser user, string title)
                                                    {
                                                        user.SetProperty(TitlePropertyName, title);
                                                    }

                                                    public static string GetTitle(this IdentityUser user)
                                                    {
                                                        return user.GetProperty<string>(TitlePropertyName);
                                                    }
                                                }

                                            然后，你就可以轻松地设置或获取额外的属性了：

                                                 user.SetTitle("My Title");
                                                 var title = user.GetTitle();   
                    */
        </script>
    </body>
</html>